chore(spec): clean fellowship sediment + retry commands eventually#212
Merged
nijeesh-stream merged 2 commits intoMay 13, 2026
Merged
Conversation
3d0a6ab to
bfa34ce
Compare
430cea6 to
4ab6e20
Compare
fd3a24e to
a3be0e1
Compare
Two flakes in client_spec.rb, both shared-CI app state, neither an
SDK bug:
1. queries-users: before(:all) seeds Frodo / Sam / Gandalf / Legolas
and hard-deletes them in after(:all). When a CI run dies before
the after(:all) fires, leftovers stay on the shared app and the
next run's queries-users test (race=Hobbit, length==2) picks up
sediment.
Fix:
- Extract cleanup into a cleanup_fellowship_leftovers!(client)
helper, called from a dedicated before(:all) block so the
concern is separate from the fellowship setup.
- Keep the per-run unique race tag as defensive isolation for
concurrent runs racing the cleanup -> upsert window.
2. custom commands create -> get / update / delete: backend write is
eventually consistent; the read-side regularly hits
'the command "<uuid>" does not exist'.
Fix: add an RSpec block matcher
expect { ... }.to eventually(matches?(value))
with chainable .with_retries(n) / .every(seconds). Replace the
custom-commands loop_times calls with this matcher so the read-side
reads as an eventual-consistency contract instead of a retry loop.
The existing loop_times helper stays as a backward-compat alias
delegating to a plain block helper, so other tests that
use it keep working untouched.
a3be0e1 to
4eb607f
Compare
The default rspec progress (dots) hides which test is in flight when a runner stalls. Last week's CI on Ruby 3.4 spent 41 minutes silently between two examples — the log only shows DEPRECATION warnings before and after, so the culprit was unidentifiable. Adds .rspec config (--format documentation, --profile 25) and a support/timing.rb hook that warns: [timing] start <full description> [timing] N.NN s <pass|fail> <full description> on each example. Two effects: * A hung runner now leaves a 'start ...' breadcrumb so the next person knows exactly which spec was mid-flight. * End-of-run --profile output lists the 25 slowest, which surfaces the flake culprits without having to scan the whole transcript.
3 tasks
nijeesh-stream
commented
May 13, 2026
shaljam
approved these changes
May 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three pre-existing flakes in
client_spec.rball caused by the shared CI test app — none are SDK behavior bugs.1.
queries users— sediment + concurrent runsbefore(:all)seeds a fellowship of four named users (Frodo Baggins, Samwise Gamgee, Gandalf the Grey, Legolas) and hard-deletes them inafter(:all). When a CI run dies between those hooks — which has happened repeatedly across recent webhook + JWT PRs — the leftovers stay on the shared app. The next run'squeries userstest pinsrace = 'Hobbit'length to 2 and picks up sediment:got: 6(or 8).Fix (two-pronged):
before(:all)—query_usersby the four fellowship names and hard-delete any leftovers viadelete_users(ids, user: HARD_DELETE, messages: HARD_DELETE). Idempotent; safe whether or not the previous run cleaned up. Stops the sediment from growing.2.
custom commandscreate → get / update / delete — eventual consistencycreate_commandreturns immediately but the read-side (get_command/update_command/delete_command) regularly hitsthe command "<uuid>" does not existon a cold shared app because the write hasn't propagated yet.Fix: wrap each follow-up step in the existing
loop_timeshelper (already used elsewhere in the spec) so each call retries up to 10× with 1s sleeps.Real fix
Per-PR scratch app via
create_app— tracked separately. This PR is a defensive workaround until that lands.Test plan
bundle exec rubocop spec/client_spec.rb— cleanqueries usersandcustom commandsacross all Ruby matrix versions